<template>
  <div class="index-page">
    <canvas id="webgl" style="height: 100%; width: 100%"></canvas>
    <div class="tag" id="tag" style="color: white; font-size: 16px; pointer-events: all"></div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted } from 'vue'
import * as THREE from 'three'
import * as dat from 'dat.gui'
// import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { EffectComposer, LightProbeGenerator, MapControls, OutlinePass, RenderPass } from 'three/examples/jsm/Addons.js'
import useMap from '@/model/use/map'
// import useEarth from '@/model/use/earth'
// import useBuilding from '@/model/use/building'
// import useWater from '@/model/use/water'
// import useCity from '@/model/use/city'

let camera: THREE.PerspectiveCamera
let scene: THREE.Scene
let composer: EffectComposer
let renderPass: RenderPass
let outlinePass: OutlinePass
let renderer: THREE.WebGLRenderer
const gui = new dat.GUI()

// 初始化渲染器、场景、相机、灯光、坐标系等
const init = () => {
  const canvas: any = document.querySelector('#webgl')
  if (canvas == null) return
  const clientWidth = canvas.clientWidth
  const clientHeight = canvas.clientHeight
  console.log(clientWidth, clientHeight)

  // 创建场景对象Scene
  scene = new THREE.Scene()

  // 相机设置 透视摄影机，fov角度，width/height比例，近 远距离
  camera = new THREE.PerspectiveCamera(75, clientWidth / clientHeight, 1, 100000)
  camera.position.set(-5, 5, 13)
  camera.up.set(0, 1, 0);
  // camera.lookAt(0, 0, 0);
  camera.updateProjectionMatrix()

  scene.add(camera)

  // 创建渲染器对象
  renderer = new THREE.WebGLRenderer({ antialias: true, canvas })
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setSize(clientWidth, clientHeight)
  renderer.setClearColor(new THREE.Color('#32373E'), 1)
  // 解决加载gltf格式模型纹理贴图和原图不一样问题
  // renderer.outputEncoding = THREE.sRGBEncoding
  renderer.shadowMap.enabled = true // 开启阴影
  renderer.toneMapping = THREE.ACESFilmicToneMapping // 色调映射
  renderer.toneMappingExposure = 2

  composer = new EffectComposer(renderer)
  renderPass = new RenderPass(scene, camera)

  composer.addPass(renderPass)
  const v2 = new THREE.Vector2(clientWidth, clientHeight)
  outlinePass = new OutlinePass(v2, scene, camera)
  outlinePass.selectedObjects = []
  outlinePass.edgeThickness = 3
  outlinePass.edgeStrength = 3
  outlinePass.visibleEdgeColor.set(0x00ff00)
  composer.addPass(outlinePass)

  initHelper()
  initEnviorment()

  // const { building } = useBuilding()
  // scene.add(building)

  const { map } = useMap({ camera, outlinePass })
  scene.add(map)

  // const { earth } = useEarth(clientWidth, clientHeight)
  // scene.add(earth)

  // const { city } = useCity()
  // scene.add(city)

  // const { water } = useWater({ scene, renderer })
  // scene.add(water)

  window.addEventListener('resize', () => {
    const width = window.innerWidth
    const height = window.innerHeight

    camera.aspect = width / height
    camera.updateProjectionMatrix()

    renderer.setSize(width, height)
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  })
}
const initHelper = () => {
  //创建控件对象 lookat失效// 设置相机控件轨道控制器OrbitControls
  // const controls = new OrbitControls(camera, renderer.domElement)
  // controls.enableDamping = true
  // controls.autoRotate = true
  const controls = new MapControls(camera, renderer.domElement);
  controls.enableDamping = true
  controls.dampingFactor = 0.25
  controls.screenSpacePanning = false
  controls.maxDistance = 800
  // 相机控件.target属性在OrbitControls.js内部表示相机目标观察点，默认0,0,0
  // console.log('controls.target', controls.target);
  // controls.target.set(0, 0, 0);
  // controls.update();// update()函数内会执行camera.lookAt(controls.targe);

  // three.js坐标轴颜色红R、绿G、蓝B分别对应坐标系的x、y、z轴，对于three.js的3D坐标系默认y轴朝上。
  const axesHelper = new THREE.AxesHelper(500)
  scene.add(axesHelper)
}

// 初始化整体环境
const initEnviorment = () => {
  // 环境光
  const ambientLight = new THREE.AmbientLight(0xadadad, 15)

  // 平行光
  const directionalLight = new THREE.DirectionalLight(0xffffff, 5)
  directionalLight.position.set(100, 100, 0)

  // 点光
  const pointLight = new THREE.PointLight(0xfafafa, 0.5)
  pointLight.position.set(100, 90, 100)

  scene.add(ambientLight, directionalLight, pointLight)

  const folderLight = gui.addFolder('Light')
  folderLight.add(ambientLight, 'intensity', 0, 100.0).name('环境光强度').step(0.1)
  folderLight.add(directionalLight, 'intensity', 0, 10.0).name('平行光强度').step(0.1)
  folderLight.add(pointLight, 'intensity', 0, 10.0).name('点光').step(0.1)

  // 光照探针-不发光。相反，光照探针存储着有关穿过3D空间的光线的信息。 渲染过程中，通过使用来自光照探针的数据，来逼近打到3D物体上的光线
  const lightProbe = new THREE.LightProbe()
  // 加载贴图材质
  const urls = [
    './source/textures/cube/px.png',
    './source/textures/cube/nx.png',
    './source/textures/cube/py.png',
    './source/textures/cube/ny.png',
    './source/textures/cube/pz.png',
    './source/textures/cube/nz.png',
  ]
  // 绘制地图
  new THREE.CubeTextureLoader().load(urls, function (cubeTexture) {
    // cubeTexture.encoding = THREE.sRGBEncoding
    // scene.background = cubeTexture;
    scene.environment = cubeTexture

    lightProbe.copy(LightProbeGenerator.fromCubeTexture(cubeTexture))
    // 销毁贴图
    cubeTexture.dispose()
  })
}

const animate = () => {
  // renderer.render(scene, camera)
  composer.render()
  requestAnimationFrame(animate)
}

onMounted(() => {
  init()
  animate()
})
</script>

<style lang="less" scoped>
.index-page {
  width: 100%;
  height: 100vh;
  position: relative;

  .tag {
    top: -50px;
    pointer-events: all;
    cursor: pointer;
    position: absolute;
  }
}
</style>